package com.genexususa.eo.google.connection;

import com.genexususa.eo.google.data.*;
import com.google.api.ads.adwords.axis.v201406.cm.*;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

import javax.xml.bind.JAXBContext;
import javax.xml.bind.Marshaller;
import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathConstants;
import javax.xml.xpath.XPathExpression;
import javax.xml.xpath.XPathFactory;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.ArrayList;
import java.util.Iterator;


public class LocationCriterionManager {


    private static final int PAGE_SIZE = 5000;
    private String _clientId;

    public void SetClientId(String clientId) {
        this._clientId = clientId;
    }

    public String GetClientId() {
        return _clientId;
    }

    public void Finalize() {

        SessionController sc = SessionController.getInstance();
        sc.RemoveSession(_clientId);
    }

    protected void getLocationsExtraData(ArrayList<LocationReport> locationReports) {
        int locationsQty = 0;
        for (LocationReport locationReport : locationReports) {
            locationsQty += locationReport.ParentIds.length;
        }
        if (locationsQty > 0) {
            int pagesQty = (int)Math.ceil((float) locationsQty / (float) PAGE_SIZE);
            int page = 0;
            String[][] locationsIdsPages = new String[pagesQty][];
            locationsIdsPages[0] = new String[PAGE_SIZE];
            int i = 0;
            for (LocationReport locationReport : locationReports) {
                for (int j = 0; j < locationReport.ParentIds.length; j++) {
                    locationsIdsPages[page][i] = String.valueOf(locationReport.ParentIds[j]);
                    i++;
                    if (i >= PAGE_SIZE) {
                        i = 0;
                        page++;
                        if (page < pagesQty - 1) {
                            locationsIdsPages[page] = new String[PAGE_SIZE];
                        } else {
                            locationsIdsPages[page] = new String[locationsQty % PAGE_SIZE];
                        }
                    }
                }
            }

            for (i=0; i<locationsIdsPages.length; i++) {
                LocationCriterion[] locationCriterions = this.getLocations(locationsIdsPages[i]);

                if (locationCriterions != null) {
                    for (LocationCriterion locationCriterion : locationCriterions) {
                        String displayType = locationCriterion.getLocation().getDisplayType();
                        if (displayType.equals("State") || displayType.equals("Country")) {
                            for (LocationReport locationReport : locationReports) {
                                for (long parentId : locationReport.ParentIds) {
                                    if (parentId == locationCriterion.getLocation().getId()) {
                                        if (displayType.equals("State")) {
                                            locationReport.ProvinceCode = locationCriterion.getLocation().getLocationName();
                                        } else {
                                            locationReport.CountryCode = locationCriterion.getLocation().getLocationName();
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }

    protected  LocationCriterion[] getLocations(String[] locationsIds){
        return this.getLocations(new Predicate[]{new Predicate("Id", PredicateOperator.IN, locationsIds)});
    }

    public LocationCriterion getLocationFromName(String displayType, String name){
        LocationCriterion[] locationCriterions = this.getLocations(new Predicate[]{new Predicate("LocationName", PredicateOperator.EQUALS, new String[]{name})});
        if (locationCriterions != null) {
            for (LocationCriterion locationCriterion : locationCriterions) {
                if (locationCriterion.getLocation().getDisplayType().equals(displayType)) {
                    return locationCriterion;
                }
            }
        }
        return null;
    }

    private LocationCriterion[] getLocations(Predicate[] predicates){
        ArrayList<LocationReport> result = new ArrayList<LocationReport>();

        // Get the instance of service's factory
        ServiceFactory sf = ServiceFactory.getInstance();

        try {
            // Get Location Criterion Service
            LocationCriterionServiceInterface locationCriterionService = sf.GetLocationCriterionService(this._clientId);

            int offset = 0;
            Selector selector = new Selector();

            selector.setPaging(new Paging(offset, PAGE_SIZE));
            //selector.setOrdering(new OrderBy[] {new OrderBy("Name", SortOrder.ASCENDING)});

            selector.setFields(new String[]{
                    "CanonicalName",
                    "Reach"
            });

            // Create predicates
            selector.setPredicates(predicates);

            return locationCriterionService.get(selector);
        } catch (Exception exc) {
            exc.printStackTrace(System.out);
        }

        return null;
    }
}
